home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / bipl.zip / PROGS.ZIP / IGREP.ICN < prev    next >
Text File  |  1992-09-28  |  6KB  |  189 lines

  1. ############################################################################
  2. #
  3. #    File:     igrep.icn
  4. #
  5. #    Subject:  Program to search in the style of egrep
  6. #
  7. #    Author:   Robert J. Alexander
  8. #
  9. #    Date:     January 28, 1992
  10. #
  11. ###########################################################################
  12. #
  13. #  Program to emulate UNIX egrep, but using the enhanced regular
  14. #  expressions supported by regexp.icn.  Options supported are nearly
  15. #  identical to those supported by egrep (no -b:  print disk block
  16. #  number).  There is one additional option, -E, to allow Icon-type
  17. #  (hence C-type) string escape sequences in the pattern string.
  18. #  BEWARE:  when -E is used, backslashes that are meant to be processed
  19. #  in the regular expression context must be doubled.  The following
  20. #  patterns are equivalent:
  21. #
  22. #    without -E:    '\bFred\b'
  23. #    with    -E:    '\\bFred\\b'
  24. #
  25. #  To enable the -D option (intended mainly for debugging), the Icon
  26. #  Program Library file "ximage" must be linked with this program.
  27. #
  28. ############################################################################
  29.  
  30. procedure Usage(n)
  31.    write(&errout,
  32.       "igrep -- emulates UNIX egrep\n_
  33.       Usage: igrep -Options [expression] filename..._
  34.     \n    Options:_
  35.     \n    c    print count of matching lines rather than actual lines_
  36.     \n    h    don't display file names_
  37.     \n    i    ignore case of letters_
  38.     \n    l    list only the names of files containing matching lines_
  39.     \n    n    precede lines with line numbers_
  40.     \n    s    work silently -- display nothing_
  41.     \n    v    invert search to display only lines that don't match_
  42.     \n    e expr    useful if expressions starts with -_
  43.     \n    E expr    expresson containing Icon escape sequences_
  44.     \n    f file    take list of alternated expressions from \"file\"",
  45.     if \xdump then
  46.     "\n    D    dump compiled pattern and quit" else "")
  47.    exit(n)
  48. end
  49.  
  50. link options,regexp
  51.  
  52. procedure main(arg)
  53.    local compiledPattern
  54.  
  55.    if *arg = 0 then Usage()
  56.    Options(arg)
  57.    compiledPattern := GetPattern(arg) |
  58.          {write(&errout,"Bad pattern ",image(Pattern)) ; exit(2)}
  59.    if \Dump then (\xdump)(compiledPattern)
  60.    exit(ScanFiles(arg,compiledPattern))
  61. end
  62.  
  63. global CountOnly, NoNames, NamesOnly, NumberLines, Out, Invert, Escapes, 
  64.       Pattern, PatternFile, Dump, Re_LeftmostShortest
  65.  
  66. procedure Options(arg)
  67.    local opt
  68.  
  69.    opt := options(arg,"chilnsve:E:f:DS")
  70.    CountOnly := opt["c"]
  71.    NoNames := opt["h"]
  72.    if \opt["i"] then Re_Filter := map
  73.    NamesOnly := opt["l"]
  74.    NumberLines := opt["n"]
  75.    Out := if \opt["s"] then &null else &output
  76.    Invert := opt["v"]
  77.    Pattern := \opt["e" | "E"]
  78.    Escapes := opt["E"]
  79.    PatternFile := opt["f"]
  80.    Dump := opt["D"]
  81.    Re_LeftmostShortest := (\opt["S"],&null) | 1
  82.    return opt
  83. end
  84.  
  85. procedure GetPattern(arg)
  86.    local f, sep
  87.  
  88.    if \PatternFile then {
  89.       f := open(PatternFile) |
  90.         stop("Can't open pattern file \"",PatternFile,"\"")
  91.       (/Pattern := "" & sep := "") | (sep := "|")
  92.       while Pattern ||:= sep || read(f) do sep := "|"
  93.       close(f)
  94.       }
  95.    /Pattern := get(arg)
  96.    if /Pattern then Usage(2)
  97.    return RePat(if \Escapes then istring(Pattern) else Pattern)
  98. end
  99.  
  100. procedure ScanFiles(arg,pattern)
  101.    local errors, Re_Longest, totalCount, fn, f, header, lineNbr, count
  102.    local line, status, lineNbrTag
  103.  
  104.    Re_Longest := 1
  105.    totalCount := 0
  106.    if *arg = 0 then arg := ["-"]
  107.    every fn := !arg do {
  108.       f := if fn == "-" then &input else open(fn) |
  109.             {write(&errout,"Can't open \"",fn,"\" -- skipped") ; errors := 2 ;
  110.         next}
  111.       header := if \NoNames | *arg = 1 then &null else fn || ":"
  112.       lineNbr := count := 0
  113.       while line := read(f) do {
  114.          lineNbr +:= 1
  115.          line := (\Re_Filter)(line)
  116.          status := ReFind(pattern,line) | &null
  117.      status := if \Invert then (\status,&null) | 1
  118.          if \status then {
  119.         count +:= 1
  120.         if count = 1 & \NamesOnly then {write(\Out,fn) ; next}
  121.         lineNbrTag := if \NumberLines then lineNbr || ":" else &null
  122.         if not \(CountOnly | NamesOnly) then
  123.           write(\Out,header,lineNbrTag,line)
  124.         }
  125.          }
  126.       close(f)
  127.       if \CountOnly then write(header,count)
  128.       totalCount +:= count
  129.       }
  130.    ## if \CountOnly & *arg > 1 then write(\Out,"** Total ** ",totalCount)
  131.    return \errors | if totalCount = 0 then 1 else 0
  132. end
  133.  
  134. #
  135. #  istring() -- Procedure to convert a string containing special escape
  136. #  constructs, of the same format as Icon source language character
  137. #  strings, to their true string representation.  Value returned is the
  138. #  string with special constructs converted to their respective
  139. #  characters.
  140. #
  141.  
  142. procedure istring(s)
  143.   local r,c
  144.   r := ""
  145.   s ? {
  146.     while r ||:= tab(upto('\\')) do {
  147.       move(1)
  148.       r ||:= case c := map(move(1)) of {
  149.     "b": "\b"        # backspace
  150.     "d": "\d"        # delete (rubout)
  151.     "e": "\e"        # escape (altmode)
  152.     "f": "\f"        # formfeed
  153.     "l": "\l"        # linefeed (newline)
  154.     "n": "\n"        # newline (linefeed)
  155.     "r": "\r"        # carriage return
  156.     "t": "\t"        # horizontal tab
  157.     "v": "\v"        # vertical tab
  158.     "x": istring_radix(16,2)# hexadecimal code
  159.     "^": char(ord(move(1)) % 32) | break # control code
  160.     default: {        # either octal code or non-escaped character
  161.       if any('01234567',c) then {    # if octal digit
  162.         move(-1)
  163.         istring_radix(8,3)
  164.       }
  165.       else c            # else non-escaped character
  166.     } | break
  167.       }
  168.     }
  169.     r ||:= tab(0)
  170.   }
  171.   return r
  172. end
  173.  
  174. procedure istring_radix(r,max)
  175.   local n,d,i,c
  176.   d := "0123456789abcdef"[1:r + 1]
  177.   n := 0
  178.   every 1 to max do {
  179.     c := move(1) | break
  180.     if not (i := find(map(c),d) - 1) then {
  181.       move(-1)
  182.       break
  183.     }
  184.     n := n * r + i
  185.   }
  186.   return char(n)
  187. end
  188.  
  189.